"""
F1 是 F beta 的 beta = 1 的特殊情况
F_beta_score =(1 + beta ^2) * (precision * recall) / (beta ^2 * precision + recall)
"""
from keras.metrics import Precision, Recall
from sklearn.metrics import recall_score, precision_score, fbeta_score


def get_data():
    """

    :return:
    """
    y_true = [0, 0, 1, 1, 0, 0, 1]
    y_pred = [0, 1, 0, 1, 0, 1, 0]

    return y_true, y_pred


def compute_fbeta(y_true, y_pred, beta):
    """

    :param y_true:
    :param y_pred:
    :param beta:
    :return:
    """
    keras_precision = Precision()
    keras_precision.update_state(y_true=y_true, y_pred=y_pred)
    keras_precision_scores = keras_precision.result().numpy()

    keras_recall = Recall()
    keras_recall.update_state(y_true=y_true, y_pred=y_pred)
    keras_recall_scores = keras_recall.result().numpy()

    sklearn_precision_scores = precision_score(y_true=y_true, y_pred=y_pred)
    sklearn_recall_scores = recall_score(y_true=y_true, y_pred=y_pred)

    keras_fbeta = \
        (1 + beta * beta) * keras_precision_scores * keras_recall_scores / \
        (beta * beta * keras_precision_scores + keras_recall_scores)
    sklearn_fbeta = \
        (1 + beta * beta) * sklearn_precision_scores * sklearn_recall_scores / \
        (beta * beta * sklearn_precision_scores + sklearn_recall_scores)

    return keras_fbeta, sklearn_fbeta


def run(beta=0.7):
    """
    主程序
    :param beta:
    :return:
    """
    y_true, y_pred = get_data()

    # 自己算
    keras_f_beta, sklearn_f_beta = \
        compute_fbeta(y_true=y_true, y_pred=y_pred, beta=beta)

    fbeta_scores = fbeta_score(y_true=y_true, y_pred=y_pred, beta=beta)

    info = 'F beta scores: fbeta score: {}, keras: {}, sklearn: {}'.\
        format(fbeta_scores, keras_f_beta, sklearn_f_beta)
    print(info)


if __name__ == '__main__':
    run()
